/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [Example_01_Serialization.java]
 * Creation Date        [09-Jul-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_09_io.serializaion;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;

/**
 * 序列化
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Example_01_Serialization {

	/**
	 * 一个内部类, 用于被序列化和反序列化 一定要实现Serializable才能够被序列化和反序列化
	 * 
	 * @author 不落的太阳(Sean Yang)
	 * @version 1.0
	 * @since JDK 6
	 * 
	 */
	static class MyClass implements Serializable {

		private static final long serialVersionUID = 2325609522495389533L;
		// 一般的实例变量会被序列化和反序列化
		private int a, b;
		// transient实例变量 不会被序列化和反序列化
		private transient int c;
		// 类变量 不会被序列化和反序列化
		private static int d;

		public MyClass() {
		}

		public MyClass(int a, int b, int c, int d) {
			this.a = a;
			this.b = b;
			this.c = c;
			MyClass.d = d;
		}

		@Override
		public String toString() {
			return a + "  " + b + "  " + c + "  " + MyClass.d;
		}
	}

	/**
	 * 序列化对象到文件
	 */
	public static void serialize(String fileName) throws Exception {
		// 创建一个对象输出流, 将对象输出到文件
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
				fileName));
		// 序列化一个字符串对象到文件
		out.writeObject("Today:");
		// 序列化当前日期对象到文件
		out.writeObject(new Date());
		// 序列化一个MyClass对象
		MyClass my1 = new MyClass(5, 6, 7, 8);
		out.writeObject(my1);
		out.close();
	}

	/**
	 * 从文件反序列化到对象
	 */
	public static void deserialize(String fileName) throws Exception {
		// 创建一个对象输入流, 从文件读取对象
		ObjectInputStream in = new ObjectInputStream(new FileInputStream(
				fileName));
		// 注意读对象时必须按照序列化对象时的顺序读, 否则会出错
		// 读取字符串对象
		String today = (String) (in.readObject());
		System.out.println(today);
		// 读日期对象
		Date date = (Date) (in.readObject());
		System.out.println(date.toString());
		// 读MyClass对象, 并调用它toString()方法
		MyClass my1 = (MyClass) (in.readObject());
		System.out.println(my1.toString());
		in.close();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		String fileName = "myClass.ser";
		serialize(fileName);
		// 注释掉第二行, 只运行下面一行, 将会发现输出不同: 静态属性的值不同
		// 不注释第二行, 静态属性值为8, 因为其在内存中存在
		// 注释掉第二行, 其值为0, 因为在序列化文件中其值为0
		deserialize(fileName);
	}

}
